package com.yzl.single;

/**
 * @program: design-pattern
 * @description: 懒汉单例设计模式:如JDK中的Desktop
 * @author: YaoZhiLi
 * @create: 2021-08-01 20:52
 */
public class SingletonLazy {
    /**
     * 构造函数私有化
     */
    private SingletonLazy() {
    }

    /**
     * 单例对象的方法
     */
    public void process() {
        System.out.println("方法调用成功");
    }

    /**
     * 第一种方式
     * 对外暴露一个方法获取类的对象
     *
     * 线程不安全，多线程下存在安全问题
     * @return
     */
//    public static SingletonLazy getInstance() {
//        if (instance==null){
//            instance=new SingletonLazy();
//        }
//        return instance;
//    }

    /**
     * 通过加锁 synchronized 保证单例
     * 采用synchronized对方法加锁有很大的性能开销
     * 解决办法：锁粒度不要那么大
     *
     * @return
     */
//    public static synchronized SingletonLazy getInstance() {
//        if (instance == null) {
//            instance = new SingletonLazy();
//        }
//        return instance;
//    }

    /**
     * 第三种方式
     * DCL 双重检查锁定 （Double-Checked-Locking）,在多线程下保持高性能
     * 这是否安全，instance=new SingletonLazy;并不是原子操作
     * 1.分配空间给对象
     * 2.在空间内创建对象
     * 3.将对象赋值给引用instance
     *
     * 加入线程1-》3-》2顺序，会把值写会给主内存，其他线程就会将读取到的instance最新的值，但是这个是不完全的对象
     * (指令重排)
     * @return
     */
//    public static SingletonLazy getInstance() {
//        if (instance == null) {
//            //A,B
//            synchronized (SingletonLazy.class) {
//                if (instance == null) {
//                    instance = new SingletonLazy();
//                }
//            }
//        }
//        return instance;
//    }

    /**
     * volatile 是java提供的关键词，可以禁止指令重排
     */
    private static volatile SingletonLazy instance;
    public static SingletonLazy getInstance() {
        //第一重检查
        if (instance == null) {
            //A,B
            synchronized (SingletonLazy.class) {
                //第二重检查
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
}